package nonthreaded;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.Segment;
import net.htmlparser.jericho.Source;
import net.htmlparser.jericho.TextExtractor;

/**
 * Normal version of the page parser
 * Provides utility for parsing a url into text and 
 * a list of urls from the resulting page.
 * @author Daniel Anderson and Luc H. Le
 * @version TCSS422 2012
 */
public class PageParser {

	/**Text parsed from page*/
	private String my_text;
	
	/**URLs parsed from page*/
	private List<URL> my_urls;
	
	/**Time spent parsing so far.*/
	private long my_parse_time;
	
	/**Number of pages parsed so far.*/
	private int my_parse_count;
	
	/**Constructor for PageParser.*/
	public PageParser() {
		my_text = "";
		my_urls = new ArrayList<URL>();
		my_parse_time = 0;
		my_parse_count = 0;
	}//end of constr
	
	/**
	 * Parses the url passed to PageParser and saves 
	 * the resulting text and urls for retrieval.
	 * @param url The url to parse.
	 * @throws IOException If Source url is invalid.
	 */
	public void parse(URL url) throws IOException {
		long start = System.currentTimeMillis();
		Source src = new Source(url);
		Segment seg = new Segment(src, 0, src.length());
		parseText(seg);
		parseURLs(seg, url.toString());
		long end = System.currentTimeMillis();
		my_parse_time = my_parse_time + end - start;
		my_parse_count++;
	}//end ofparse

	/**
	 * Get method for the parsed text.
	 * @return The text from the page.
	 */
	public String getText() {
		return my_text;
	}//end of get

	/**
	 * Get method for the list of URLs found in parsed text.
	 * @return The urls found.
	 */
	public List<URL> getHyperlinks() {
		return my_urls;
	}//end of get
	
	/**
	 * Get method for amount of time this object has been parsing.
	 * @return The parse time in milliseconds.
	 */
	public long getParseTime() {
		return my_parse_time;
	}
	
	/**
	 * Get method for number of pages parsed.
	 * @return Number of pages parsed.
	 */
	public int getParseCount() {
		return my_parse_count;
	}//end of get

	/**
	 * Parses the text of the page passed into a single string.
	 * @param seg The segment of html to parse text from.
	 */
	private void parseText(Segment seg) {
		TextExtractor te = new TextExtractor(seg);
		my_text = te.toString();
	}//end of get

	/**
	 * Parses a segment of html into seperate URLs.
	 * @param seg The segment of html to parse.
	 * @param parent The webpage url of the segment.
	 */
	private void parseURLs(Segment seg, String parent) {
		List<Element> e = seg.getAllElements(HTMLElementName.A);
		my_urls = new ArrayList<URL>(); //clear old urls
		for(int i = 0; i < e.size(); i++) {
			if(e.get(i).getAttributeValue("href") != null) {
				try {
					String url = buildURL(parent, e.get(i).getAttributeValue("href").toString());
					if(url != "null")
						my_urls.add(new URL(url));
				} catch (MalformedURLException e1) {
					System.out.println("Something went wrong in PageParser: MalformedURLException");
				}
			}
		}
	}//end of parseURLs

	/**
	 * Takes the absolute URL and possible relative URL and produces a valid URL.
	 * @param prime URL source of the current url.
	 * @param sub Current URL that may be relative or absolute.
	 * @return A complete valid url.
	 * @throws MalformedURLException URL created is not valid.
	 */
	private String buildURL(String prime, String sub) throws MalformedURLException {
		String str = "null";
		
		if(!prime.endsWith("/")) {
			prime = prime.substring(0, prime.lastIndexOf("/") + 1);
		} 
		if(sub.startsWith("/")) {
			sub = sub.substring(1);
		}
		if(sub.endsWith(".txt") || sub.endsWith(".html") || sub.endsWith("/")){
			str = prime + sub;
		}
		if(sub.startsWith("http://")) {
			str = sub;
		}
		return str;
	}//end of buildURL
}//end of PageParser
